package logger

import (
	"encoding/json"
	"fmt"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/sirupsen/logrus"
	"go-iot-gateway/internal/apk/files"
	sys_config "go-iot-gateway/internal/sys/config"
	"io"
	"os"
	"strings"
	"time"
)

var (
	connectorLogger *logrus.Logger
	storageLogger   *logrus.Logger
	schedulerLogger *logrus.Logger
	webLogger       *logrus.Logger
	processorLogger *logrus.Logger
)

// web模块 日志
func Web() *logrus.Logger {
	if webLogger == nil {
		panic("Web logger 还未初始化")
	}
	return webLogger
}

// 定时模块 日志
func Scheduler() *logrus.Logger {
	if schedulerLogger == nil {
		panic("Scheduler logger 还未初始化")
	}
	return schedulerLogger
}

// 存储模块 日志
func Storage() *logrus.Logger {
	if storageLogger == nil {
		panic("Storage logger 还未初始化")
	}
	return storageLogger
}

// 通道日志 - 每个通道一个日志
func Connector() *logrus.Logger {
	if connectorLogger == nil {
		panic("Connector logger 还未初始化")
	}
	return connectorLogger
}

// 数据处理日志
func Processor() *logrus.Logger {
	if processorLogger == nil {
		panic("Processor logger 还未初始化")
	}
	return processorLogger
}

// NewChannelLogger 创建通道日志
func NewChannelLogger(logName string) *logrus.Logger {
	sysConfig := sys_config.ConfigInfo()
	loggingEnv := &sysConfig.Logging
	logger := logrus.New()
	setLogConfig("chl_"+logName, logger, sysConfig.HomeDir, loggingEnv)
	return logger
}

// 日志初始化
func InitLogger(sysConfig *sys_config.SysConfigInfo) {

	fmt.Printf("\n===== 初始化LOGGER ===== \n")
	jsonData, _ := json.Marshal(sysConfig.Logging)
	fmt.Printf("%s \n", string(jsonData))

	webLogger = logrus.New()
	schedulerLogger = logrus.New()
	storageLogger = logrus.New()
	connectorLogger = logrus.New()
	processorLogger = logrus.New()

	setLogConfig("gateway", logrus.StandardLogger(), sysConfig.HomeDir, &sysConfig.Logging)
	setLogConfig("web", webLogger, sysConfig.HomeDir, &sysConfig.Logging)
	setLogConfig("scheduler", schedulerLogger, sysConfig.HomeDir, &sysConfig.Logging)
	setLogConfig("storage", storageLogger, sysConfig.HomeDir, &sysConfig.Logging)
	setLogConfig("connector", connectorLogger, sysConfig.HomeDir, &sysConfig.Logging)
	setLogConfig("processor", processorLogger, sysConfig.HomeDir, &sysConfig.Logging)
}

var isPrint = false

func printOnce(str string) {
	if isPrint {
		return
	}
	isPrint = true
	fmt.Println(str)
}

// 配置日志
func setLogConfig(name string, log *logrus.Logger, homeDir string, loginConfig *sys_config.LoggingEnv) {

	logName := name + ".log"

	// 输出中添加文件名和方法信息
	log.SetReportCaller(loginConfig.PrintReportCaller)

	outPutMap := make(map[string]string, 10)
	for _, output := range strings.Split(loginConfig.Output, ",") {
		output = strings.TrimSpace(output)
		if output == "" {
			continue
		}

		outPutMap[strings.ToLower(output)] = output
	}

	writers := []io.Writer{}

	for _, output := range outPutMap {

		switch output {
		case "stdout":
			writers = append(writers, os.Stdout)
		case "file":
			maxHistory := loginConfig.MaxHistory
			if maxHistory <= 0 {
				maxHistory = 30
			}

			maxAge := time.Duration(maxHistory*24) * time.Hour

			maxFileSize := int64(loginConfig.MaxFileSizeMb)
			if maxFileSize <= 0 {
				maxFileSize = 1 * 1024 * 1024 * 1024 //1g
			} else {
				maxFileSize = maxFileSize * 1024 * 1024
			}

			path := homeDir + string(os.PathSeparator) + "logs" // 默认路径
			if strings.TrimSpace(loginConfig.Path) != "" {
				path = strings.TrimSpace(loginConfig.Path)
			}

			path, err := files.Mkdir(path)

			if err != nil {
				logrus.Error("%s 日志输出到文件配置失败", logName)
				continue
			}
			printOnce("日志输出路径 :" + path)
			path = path + string(os.PathSeparator) + logName

			ops := make([]rotatelogs.Option, 0, 8)
			ops = append(ops, rotatelogs.WithLinkName(path))
			ops = append(ops, rotatelogs.WithRotationSize(maxFileSize))                 //按大小切分日志
			ops = append(ops, rotatelogs.WithRotationTime(time.Duration(24)*time.Hour)) //每天生成一个

			if loginConfig.MaxFileCount > 0 { //按个数保留
				ops = append(ops, rotatelogs.WithRotationCount(loginConfig.MaxFileCount))
			} else { //按时间保留
				ops = append(ops, rotatelogs.WithMaxAge(maxAge))
			}

			logoutWriter, err := rotatelogs.New(path+".%Y%m%d", ops...) //按时间切分日志
			if err != nil {
				logrus.Error("日志配置失败", err)
			}

			writers = append(writers, logoutWriter)
		default:
			//不处理
		}
	}

	if len(writers) == 0 {
		writers = append(writers, os.Stdout)
	}

	log.SetOutput(io.MultiWriter(writers...))

	switch strings.ToLower(loginConfig.Formatter) {
	case "text":
		log.SetFormatter(&logrus.TextFormatter{})
	case "json":
		log.SetFormatter(&logrus.JSONFormatter{})
	default:
		log.SetFormatter(&logrus.TextFormatter{})
	}

	switch strings.ToLower(loginConfig.Level) {
	case "error":
		log.SetLevel(logrus.ErrorLevel)
	case "warn":
		log.SetLevel(logrus.WarnLevel)
	case "info":
		log.SetLevel(logrus.InfoLevel)
	case "debug":
		log.SetLevel(logrus.DebugLevel)
	default:
		log.SetLevel(logrus.WarnLevel)
	}

}
